package sk.fei.vrml.objects;

import java.util.Iterator;
import java.util.LinkedList;

import sk.fei.vrml.main.Constants;

import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;

/**
 * Uzol transformarmacie objeku/ov
 * @author Noxtrip
 * 
 * http://www.lighthouse3d.com/vrml/tutorial/index.shtml?trans
 * 
 * Transform {
 *	    scale 1 1 1 
 *      scaleOrientation 0 0 1 0 
 *	    center 0 0 0 
 *	    rotation 0 0 1 0 
 *	    translation 0 0 0 
 *	    bboxCenter 0 0 0
 *	    bboxSize -1 -1 -1
 *	    children [] 
 * } 
 *
 */
public class VrmlTransform extends VrmlObject{
	
	private float[] center = {0,0,0};
	private float[] rotation = {0,0,0,0};
	private float[] translation = {0,0,0};
	private float[] scale = {1,1,1};
	private float[] scaleOrientation = {0,0,0,0};
	private float[] bboxCenter = {0,0,0};
	private float[] bboxSize = {-1,-1,-1};
	
	private LinkedList<VrmlObject> children = new LinkedList<VrmlObject>();
	
	public VrmlTransform() {
		this.type = Constants.Transform;
	}
	
	public VrmlTransform(VrmlShape shape){
		children.add(shape);
		this.type = Constants.Transform;
	}
	
	public VrmlTransform(LinkedList<VrmlObject> shapes) {
		this.children = shapes;
		this.type = Constants.Transform;
	}
	
	public void applyTransformation(GLAutoDrawable GLAutoDrawable){
		synchronized(this){
			GL gl = GLAutoDrawable.getGL(); 
			gl.glPushMatrix();
			//posunutie
			gl.glTranslatef(translation[0], translation[1], translation[2]);
			// rotacia okolo troch osi
			gl.glTranslatef(center[0], center[1], center[2]); // toto je nastavuje center scalingov a rotacii
			/*gl.glRotatef(rotationX[0],rotationX[1],rotationX[2],rotationX[3]);
			gl.glRotatef(rotationY[0],rotationY[1],rotationY[2],rotationY[3]);
			gl.glRotatef(rotationZ[0],rotationZ[1],rotationZ[2],rotationZ[3]);*/
			gl.glRotatef(rotation[0],rotation[1],rotation[2],rotation[3]);
			//scaling
			//gl.glTranslatef(center[0], center[1], center[2]); // toto je nastavuje center scalingov a rotacii
			gl.glScalef(scale[0], scale[1], scale[2]);
			gl.glTranslatef(-center[0], -center[1], -center[2]);// potialto nastavuje center scalingu
			gl.glRotatef(scaleOrientation[3],scaleOrientation[0],scaleOrientation[1],scaleOrientation[2]);
			//System.out.println(scaleOrientation[0]+" "+scaleOrientation[1]+" "+scaleOrientation[2]+" "+scaleOrientation[3]);
		
			Iterator<VrmlObject> it = children.iterator();
			while (it.hasNext()){
				Object obj = it.next();
				if (obj instanceof VrmlTransform){
					VrmlTransform transformation = (VrmlTransform)obj;
					transformation.applyTransformation(GLAutoDrawable);
				}
				else{
					VrmlShape shape = (VrmlShape)obj;
					shape.getGeometry().draw(GLAutoDrawable,shape.getAppearence());
				}
			}
		
			// ovplyvnuje len svoje deti preto zrusime transformaciu
			//cancelTransformation(GLAutoDrawable);
			gl.glPopMatrix();
		}
	}
	
	/**  Vdaka push pop metrix nie je treba ale zatial nemazat!!!!!!!!!!
	 */
	/*public void cancelTransformation(GLAutoDrawable GLAutoDrawable){
		GL gl = GLAutoDrawable.getGL(); 
		gl.glRotatef(-rotationX[0],rotationX[1],rotationX[2],rotationX[3]);
		gl.glRotatef(-rotationY[0],rotationY[1],rotationY[2],rotationY[3]);
		gl.glRotatef(-rotationZ[0],rotationZ[1],rotationZ[2],rotationZ[3]);
		gl.glTranslatef(-translation[0], -translation[1], -translation[2]);
	}*/
	
	public void setRotationX(float rotation){
		this.rotation[1] = rotation;
	}
	
	public void setRotationY(float rotation){
		this.rotation[2] = rotation;
	}
	
	public void setRotationZ(float rotation){
		this.rotation[3] = rotation;
	}
	
	public void setRotationAngle(float rotation){
		this.rotation[0] = rotation;
	}
	
	public LinkedList<VrmlObject> getChildren(){
		return children;
	}
	
	public void addChild(VrmlObject child) {
		synchronized(this){
			children.add(child);
		}
	}
	
	public float[] getTranslation(){
		return translation;
	}
	
	public float getRotationX(){
		return rotation[1];
	} 
	
	public float getRotationY(){
		return rotation[2];
	} 
	
	public float getRotationZ(){
		return rotation[3];
	} 
	
	public float getRotationAngle(){
		return rotation[0];
	} 
	
	public float[] getCenter(){
		return center;
	}
	
	public String toString() {
		return "Properties";
	}
	
	public float[] getScale() {
		return scale;
	}
	
	public float getScaleX() {
		return scale[0];
	}
	
	public float getScaleY() {
		return scale[1];
	}
	
	public float getScaleZ() {
		return scale[2];
	}
	
	public void setScaleX(float scale){
		this.scale[0] = scale;
	}
	
	public void setScaleY(float scale){
		this.scale[1] = scale;
	}
	
	public void setScaleZ(float scale){
		this.scale[2] = scale;
	}
	
	public void setScale(float[] scale){
		this.scale[0] = scale[0];
		this.scale[1] = scale[1];
		this.scale[2] = scale[2];
	}
	
	public float[] getScaleOrientation() {
		return scaleOrientation;
	}
	
	public float[] getBboxCenter() {
		return bboxCenter;
	}
	
	public float[] getBboxSize() {
		return bboxSize;
	}
	
	public void setTranslation(float[] translation) {
		this.translation = translation;
	}
	
	public void setScaleOrientation(float[] scaleOrientation) {
		this.scaleOrientation = scaleOrientation;
	}
	
	public void setBboxSize(float[] bboxSize) {
		this.bboxSize = bboxSize;
	}
	
	public void setChildren(LinkedList<VrmlObject> shapes) {
		this.children = shapes;
	}
	
	public void removeChild(VrmlObject obj){
		this.children.remove(obj);
	}
	
	public void setBboxCenter(float[] bboxCenter) {
		this.bboxCenter = bboxCenter;
	}
	
	public void setCenter(float[] center) {
		this.center = center;
	}
	
	public float getTranslationX(){
		return translation[0];
	}
	
	public float getTranslationY(){
		return translation[1];
	}
	
	public float getTranslationZ(){
		return translation[2];
	}
	
	public void setTranslationX(float x){
		translation[0]=x;
	}
	
	public void setTranslationY(float y){
		translation[1]=y;
	}
	
	public void setTranslationZ(float z){
		translation[2]=z;
	}
	
	public void setScaleOrientationX(float orientation){
		this.scaleOrientation[0] = orientation;
	}
	
	public void setScaleOrientationY(float orientation){
		this.scaleOrientation[1] = orientation;
	}
	
	public void setScaleOrientationZ(float orientation){
		this.scaleOrientation[2] = orientation;
	}
	
	public void setScaleOrientationDeg(float deg){
		this.scaleOrientation[3] = deg;
	}
	
	public float getScaleOrientationX(){
		return scaleOrientation[0];
	}
	
	public float getScaleOrientationY(){
		return scaleOrientation[1];
	}
	
	public float getScaleOrientationZ(){
		return scaleOrientation[2];
	}
	
	public float getScaleOrientationDeg(){
		return scaleOrientation[3];
	}
	
	public float getScaleCenterX(){
		return center[0];
	}
	
	public float getScaleCenterY(){
		return center[1];
	}
	
	public float getScaleCenterZ(){
		return center[2];
	}

	public void setScaleCenterX(float center){
		this.center[0] = center;
	}
	
	public void setScaleCenterY(float center){
		this.center[1] = center;
	}
	
	public void setScaleCenterZ(float center){
		this.center[2] = center;
	}
	
}
